/*
 * @Author: Dannycjh 2233879049@qq.com
 * @Date: 2023-04-15 11:57:11
 * @LastEditors: Dannycjh 2233879049@qq.com
 * @LastEditTime: 2023-04-28 14:47:26
 * @FilePath: \cc-game-development-template\assets\game.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/*
 * @Author: Dannycjh 2233879049@qq.com
 * @Date: 2023-04-15 11:57:11
 * @LastEditors: Dannycjh 2233879049@qq.com
 * @LastEditTime: 2023-04-17 09:04:56
 * @FilePath: \cc-game-development-template\assets\scripts\game.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { _decorator, Node, Prefab, resources, tween, Vec3, instantiate, find, MeshRenderer, Animation } from 'cc';
import { App } from '../../../App';
import UtilTool from '../../../tools/UtilTool';
import BilliardsGameController from '.././controller/BilliardsGameController';
import { Ball } from '../Ball';
import { GameLayer5 } from './GameLayer5';
import { GameBaseModel } from '../GameBaseModel';
import { EndLayer5 } from './EndLayer5';
import { BLOOD_PLAYDRAGON_ANIM, FOUR_BALL_BASE } from '../GameManage';
import { GameBloodLogic } from './GameBloodLogic';
import { GamePlayState } from '../GameBaseLogic';
import { Role } from '../Role';
import { PD } from '../../../player/PlayerData';
import { showChangeScore, showGameFourMora, showScoreParticle } from '../../../tools/PopuUp';
import { Material } from 'cc';
import { Vec2 } from 'cc';
import { GameBloodArea } from './GameBloodArea';
import { UITransform } from 'cc';
import { GameBloodRoleScore } from './GameBloodRoleScore';
const { ccclass, property } = _decorator;

// 游戏主脚本
@ccclass('GameModel5')
export class GameModel5 extends GameBaseModel {
    @property(Prefab)
    GameMoraPrefab : Prefab = null;   // 猜拳预制体

    @property(Prefab)
    GameAreaPrefab : Prefab = null;   // 圆形区域预制体

    @property(Material)
    scoreMaterial : Material[] = [];   // 分数材质

    gameLayerCtrl:GameLayer5 = null
    gameLogic : GameBloodLogic = null
    moraPanel:Node = null    // 猜拳界面

    frameHz = 6     // 帧同步请求频率 (频率越小，同步越频繁)
    frameCount = 0  // 帧数

    areaNode :GameBloodArea[] = []   // 圆形区域节点
    dragonAnim:Animation = null
    dragonAnim3:Animation = null
    dragonAnim4:Animation = null

    changeScoretime = 1700      // 金币飘分动画时间
    scoreParticletime = 2200    // 金币粒子动画时间
    scoreToWinertime = 2000     // 金币从一个玩家飞向另一个玩家时间

    protected onLoad(): void {
        super.onLoad();
    }

    protected onEnable(): void {
        super.onEnable();
    }
    
    start() {
        super.start();
        App.WSGameStatus = 4
        this.gameLayerCtrl = this.getGameLayerCtrl(GameLayer5)
        this.gameLogic = new GameBloodLogic()

        // this.cueCtrl.showCue(false,this.cueCtrl.ballToCueAngle(this.getWhiteToOneAngle()))
        this.setAllBallShow(false)

        tween(this.node).delay(0.1).call(()=>{
            this.gameLogic.initGame()
        }).start()

        if (App.Model.gameManage.isReconnectAndGameing() /* && App.Model.gameManage.isReconnectAndGameing().currentRoomStatus==2 */){
            tween(this.node).delay(0.2).call(()=>{
                this.setAllBallShow(true)
                this.gameLogic.setPlayState(GamePlayState.GAME_START)
            }).start()
        }
        else{
            this.showMoraPanel()
        }

        // 在场景里面添加圆形区域预制件
        for (let i = 0; i < 5; i++) {
            if (this.GameAreaPrefab) { 
                let areaNode = instantiate(this.GameAreaPrefab);
                let areaCtrl = areaNode.getComponent(GameBloodArea)
                this.node.addChild(areaNode);
                areaNode.active = false

                this.areaNode.push(areaCtrl)
            }
        }

        // 龙动画
        this.dragonAnim = find('Canvas/animNode/dragonAnim').getComponent(Animation)
        this.dragonAnim3 = find('Canvas/animNode/dragonAnim3').getComponent(Animation)
        this.dragonAnim4 = find('Canvas/animNode/dragonAnim4').getComponent(Animation)

        this.dragonAnim.node.active = false
        this.dragonAnim3.node.active = false
        this.dragonAnim4.node.active = false
        this.dragonAnim.on(Animation.EventType.FINISHED, this.animFinish, this)
        this.dragonAnim3.on(Animation.EventType.FINISHED, this.animFinish, this)
        this.dragonAnim4.on(Animation.EventType.FINISHED, this.animFinish, this)
    }
    
    /**
     * 游戏开始
     */
    gameStart() {
        if (App.Model.gameManage.isReconnectAndGameing() /* && App.Model.gameManage.isReconnectAndGameing().currentRoomStatus==2 */) {
            this.gameLogic.respGameReconnect(App.Model.gameManage.gameReconnectData)
        }
        else{
            // this.cueCtrl.showCue(false,this.cueCtrl.ballToCueAngle(this.getWhiteToOneAngle()))

        }
    }

    /**  
     * 显示猜拳界面
    */
    showMoraPanel() {
        // this.moraPanel = showGameFourMora(this.viewNode)
        this.moraPanel = instantiate(this.GameMoraPrefab)
        this.moraPanel.parent = this.viewNode
    }

    // 初始化四球开伦台球，台球一字型排列
    initTableBallsBlood() {
        App.Model.gameManage.otherBallArr = []
        App.Model.gameManage.otherBallArrUI = []

        for(let i=1; i<=8; i++) {
            let ball = instantiate(this.ballPrefab);
            this.node.addChild(ball);

            ball.getComponent(Ball).init(i);
            App.Model.gameManage.otherBallArr.push(ball)
        }

        this.resetAllBallPosBlood(false)
        
    }

    /**  
     * 重新摆球
     * @param isMine 是否是自己击打
    */
    resetAllBallPosBlood(isMine=true) {
        let whiteBallInfo = this.gameLogic.getBallInfoByNumber(0)
        this.setBallSleep(this.whiteBall)
        this.whiteBall.position = new Vec3(whiteBallInfo.posX, whiteBallInfo.posY, whiteBallInfo.posZ);
        
        this.whiteBall.getComponent(Ball).init(0);
        this.whiteBall.getComponent(Ball).setDefault();
        this.whiteBall.active = true

        for(let i=1; i<=8; i++) {
            let ball = this.getBallByNumber(i)
            this.setBallSleep(ball)

            let ballInfo = this.gameLogic.getBallInfoByNumber(i)
            let pos = new Vec3(ballInfo.posX, ballInfo.posY, ballInfo.posZ);
    
            ball.node.setPosition(pos);
            ball.node.active = true
            ball.setDefault()
        }
        
        this.cueCtrl.showCue(isMine)
    }

    /** 
     * 播放龙动画
      */
    playDragonAnim(allScore) {
        // UtilTool.printLog("播放龙动画", allScore)
        if(allScore<BLOOD_PLAYDRAGON_ANIM) {
            App.Audio.playOneShot("game/coinAnim_1")
            this.dragonAnim3.node.active = true
            this.dragonAnim3.play('dragonAnimation3')
        }
        else if (allScore<BLOOD_PLAYDRAGON_ANIM+16) {
            App.Audio.playOneShot("game/coinAnim_2")
            this.dragonAnim4.node.active = true
            this.dragonAnim4.play('dragonAnimation4')
        }
        else {
            App.Audio.playOneShot("game/dragon")
            this.dragonAnim.node.active = true
            this.dragonAnim.play('dragonNnimation')
        }
    }

    // 播放龙动画回调
    animFinish() {
        this.dragonAnim.node.active = false
        this.dragonAnim3.node.active = false
        this.dragonAnim4.node.active = false
    }

    // 设置球显示隐藏
    setAllBallShow(show=true) {
        if (show) {
            this.whiteBall.active = true
            App.Model.gameManage.otherBallArr.forEach(item => {
                item.active = true
            });
        }
        else{
            this.whiteBall.active = false
            App.Model.gameManage.otherBallArr.forEach(item => {
                item.active = false
            });
        }
    }

    // 收到球进洞事件
    ballInRoleEvent(ballNumber : number, ballNode : Node, role : Role) {
        if  (!this.node) return;
        this.gameLogic.ballInRoleEvent(ballNumber, ballNode, role)
    }

    // 展示得分区域分数动画
    showChangeScore_Area() {
        let isWhiteBallInRole = this.gameLogic.ballInRoleList.includes(0)
        if (!isWhiteBallInRole && this.gameLogic.ballInRoleList.length>0){
            if (this.gameLogic.areaCollideList.length>0 && this.gameLogic.areaScoreMap){

                // 底分位置
                let endPos = this.gameLayerCtrl.changeScore.node.getPosition()
                let endWordPos = this.gameLayerCtrl.changeScore.node.parent.getComponent(UITransform).convertToWorldSpaceAR(endPos)
                endWordPos = UtilTool.UIPosToLocalPos(endWordPos)

                for (let i = 0; i < this.gameLogic.areaCollideList.length; i++) {
                    let num = this.gameLogic.areaCollideList[i];
                    let score = this.gameLogic.areaScoreMap[num.toString()].score

                    let areaCtrl = this.getAreaNode(num)
                    if(areaCtrl) {
                        let startPos = this.World3DToLocal(areaCtrl.node.getWorldPosition())

                        // 金币粒子动画
                        showScoreParticle({
                            "startPos":startPos,
                            "endPos":new Vec2(endWordPos.x, endWordPos.y),
                            "func":()=>{
                                if (this.node) {
                                    if (i==this.gameLogic.areaCollideList.length-1){ // 最后一次金币粒子动画
                                        this.gameLayerCtrl.UpdataAnteScore(null, null, score, true)
                                    }else{
                                        this.gameLayerCtrl.UpdataAnteScore(null, null, score)
                                    }
                                }
                            },
                        },this.effNode)
                    }
                }
            }
        }

        // 未进球
        if (this.gameLogic.ballInRoleList.length==0) {
            showChangeScore({
                "score": 0,
                "pos": new Vec2(0, 0),
                "tip": App.language.getLanguageLab(200),
                "func": ()=>{
                }
            })
        }
    }

    // 收到球进洞得分事件
    ballInRoleScoreEvent(ballNumber: number, oneRoleNumber: number, role : Role) {
        if  (!this.node) return;
        let pos = this.World3DToLocal(role.node.getWorldPosition())
        let endPos = this.gameLayerCtrl.changeScore.node.getPosition()
        let endWordPos = this.gameLayerCtrl.changeScore.node.parent.getComponent(UITransform).convertToWorldSpaceAR(endPos)
        endWordPos = UtilTool.UIPosToLocalPos(endWordPos)

        if (pos.x<-100){
            pos.x = pos.x + 100
        }
        // 进球得分
        if (ballNumber!=null) {
            let isShow = false
            let isWhiteBall = false
            if (ballNumber==0) {
                // 白球进洞扣600分
                isShow = true
                isWhiteBall = true
                ballNumber = -PD.bloodConfig.whiteBallInHoleDeductScore
            }
            else{
                // 非白球进洞
                if (this.whiteBall.active) {
                    isShow = true
                }
            }

            if (isShow) {
                // 金币文本动画
                showChangeScore({
                    "score": ballNumber,
                    "pos": pos,
                    "tip": isWhiteBall?App.language.getLanguageLab(199):App.language.getLanguageLab(197),
                    "func": ()=>{
                        if (this.node) {
                            if (ballNumber>0) {
                                // 金币粒子动画
                                showScoreParticle({
                                    "startPos":pos,
                                    "endPos":new Vec2(endWordPos.x, endWordPos.y),
                                    "func":()=>{
                                        if (this.node) {
                                            this.gameLayerCtrl.UpdataAnteScore(ballNumber)
                                        }
                                    }
                                },this.effNode)
                            }
                            else if (ballNumber<0) {
                                this.gameLayerCtrl.UpdataAnteScore(ballNumber)
                            }
                        }
                    }
                })
            }
        }

        // 进袋得分
        if (oneRoleNumber!=null && ballNumber!=0 && this.whiteBall.active) { 
            if (this.gameLogic.holeScoreMap) {
                let score = this.gameLogic.holeScoreMap[oneRoleNumber.toString()]
                setTimeout(() => {
                    showChangeScore({
                        "score": score,
                        "pos": pos,
                        "tip": App.language.getLanguageLab(198),
                        "func": ()=>{
                            if (this.node) {
                                this.gameLayerCtrl.UpdataAnteScore(null,score)
                            }
                        }
                    })
                }, 1000)
            }
        }
    }

    // 收到开始击球事件
    startHitBallEvent(event) {
        UtilTool.printLog("GameModel1 start hit ball")
        this.gameLogic.startHitBallEvent(event)
        this.gameLayerCtrl.stopTimeSchedule()
        this.frameCount = this.frameHz
    }
    
    // 收到白球碰撞球事件
    whiteBallContactEvent(ballNumber : number) {
        UtilTool.printLog("GameModel4 收到白球碰撞球事件")
        this.isOpenBallStatus = false
        if(!this.gameLogic) {
            return // 游戏开始时会有碰球的情况
        }

        this.gameLogic.whiteBallContactEvent(ballNumber)

    }

    // 收到摆球结束事件
    whiteBallPosEndEvent(whiteBallPos) {
        UtilTool.printLog("GameModel1 white ball pos end", whiteBallPos)
        this.gameLogic.whiteBallPosEndEvent(whiteBallPos)
    }

    // 收到击球结束事件
    hitBallEndEvent() {
        this.gameLogic.hitBallEndEvent()
        
    }

    update(deltaTime: number) {
        super.update(deltaTime)

        this.frameCount = this.frameCount + 1

        // 当前玩家是自己，并且是在击球的状态则上报帧同步
        if (this.frameCount >= this.frameHz) {
            if (this.gameLogic.curPlayUser && this.gameLogic.isMineAccount(this.gameLogic.uploadAccount) && this.gameLogic.curPlayState==GamePlayState.HIT_BALL) {
                this.frameCount = 0
                this.reqFrameDataMsg()
            }
        }
        
    }

    // 根据区域编号获取指定区域
    getAreaNode(level) {
        let areaCtrl = null
        for (let index = 0; index < this.areaNode.length; index++) {
            let pAreaCtrl:GameBloodArea = this.areaNode[index];
            if (pAreaCtrl.level == level) {
                areaCtrl = pAreaCtrl
                break 
            }
        }

        return areaCtrl
    }

    /////////////////////////////////////////////////////////////// 请求消息 ////////////////////////////////////////////////////////////////////
    /**
     * 请求认输
     */
    reqGiveUpMsg(cb) {
        // let controller = this.controller as BilliardsGameController
        // controller.reqGiveUpMsg(cb)
    }

    /**
     * 请求调整球杆角度
     */
    reqChangeCueMsg(cueAngle) {
        let controller = this.controller as BilliardsGameController
        controller.reqChangeCueMsg(cueAngle)
    }

    /**
     * 请求玩家击球
     * @param cueAngle 球的角度
     * @param dynamics 力度
     */
    reqHitballMsg(angle, dynamics) {
        let controller = this.controller as BilliardsGameController
        controller.reqHitballMsg(angle, dynamics)
    }

    /** 
     * 请求上报帧数据
     */
    reqFrameDataMsg() {
        let controller = this.controller as BilliardsGameController
        let allBallInfo = this.gameLogic.getAllBallPos()
        controller.reqFrameDataMsg(allBallInfo)
    }

    /**
     * 请求球桌运动结束，上报击球结果（血流到底）
     * @param wheel 轮数,标识着是上传的第几轮的击球结果
     * @param allBallInfo 各个球的信息
     * @param enterBall 进洞的球号
     * @param areaList  触碰到的区域的编号
     * @param holeList  触碰到的球洞的编号
     */
    reqHitballEndBloodMsg(wheel, allBallInfo, enterBall, areaList, holeList) {
        if (this.gameLogic.curPlayState == GamePlayState.GAME_END) {
            return
        }
        let controller = this.controller as BilliardsGameController
        controller.reqHitballEndBloodMsg(wheel, allBallInfo, enterBall, areaList, holeList)
    }
    
    
    /////////////////////////////////////////////////////////////// 请求消息 ////////////////////////////////////////////////////////////////////


    /**
     * 游戏结束
     */
    public gameOver(data) {
        resources.load('prefabs/game/layer5/GameEndLayer5',Prefab,(err,prefabs) =>{
            let layerNode = instantiate(prefabs);
            this.viewNode.addChild(layerNode);

            if (PD.user.addressUrl == data.winPlayerAccount) {
                layerNode.getComponent(EndLayer5).showView(data, 1)
            }
            else {
                layerNode.getComponent(EndLayer5).showView(data, 2)
            }
        })
    }

    onDestroy() {
        App.WSGameStatus = 0
    }

}

